import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 面试题 08.12. 八皇后
 * https://leetcode-cn.com/problems/eight-queens-lcci/
 */
public class Solutions_mianshi_08_12 {
    public static void main(String[] args) {
        int n = 4;
        List<List<String>> result = solveNQueens(n);
        System.out.println(result);
    }

    private static List<List<String>> res = null;
    private static boolean[] colFlag = null;
    private static boolean[] mainFlag = null;
    private static boolean[] secondFlag = null;
    private static char[] arr = null;

    public static List<List<String>> solveNQueens(int n) {
        arr = new char[n];
        Arrays.fill(arr, '.');
        res = new ArrayList<>();
        // colFlag[3] = true，第 3 列，有皇后存在
        colFlag = new boolean[n];
        // mainFlag[0] = true，主对角线上 i - j = 0 上，有皇后存在
        mainFlag = new boolean[2 * n];
        // secondFlag[3] = true，副对角线上 i + j = 3 上，有皇后存在
        secondFlag = new boolean[2 * n];
        // col[1] = 3，表示第 2 行的皇后在索引 3 上
        int[] col = new int[n];
        backtrack(0, n, col);
        return res;
    }

    public static void backtrack(int i, int n, int[] col) {
        if (i == n) {
            // 根据 col 生成棋盘
            generator(col);
        }
        // 遍历第 [0, n) 列，是否可以将皇后放置在 [i, j] 位置上
        for (int j = 0; j < n; j++) {
            if (colFlag[j]) {
                // 列上存在皇后
                continue;
            }
            if (mainFlag[i - j + n]) {
                // 主对角线上存在皇后
                continue;
            }
            if (secondFlag[i + j]) {
                // 副对角线上存在皇后
                continue;
            }
            col[i] = j;
            // 标记状态
            colFlag[j] = true;
            mainFlag[i - j + n] = true;
            secondFlag[i + j] = true;
            backtrack(i + 1, n, col);
            // 还原状态
            colFlag[j] = false;
            mainFlag[i - j + n] = false;
            secondFlag[i + j] = false;
        }
    }

    public static void generator(int[] col) {
        List<String> list = new ArrayList<>();
        // 根据 col 填充棋盘
        for (int i = 0; i < col.length; i++) {
            arr[col[i]] = 'Q';
            list.add(new String(arr));
            arr[col[i]] = '.';
        }
        res.add(list);
    }
}
